<template>
	<view class="container">
		<template>
		  <view class="container">
		    <view class="button-row top">
		      <button v-for="index in gridLine" :key="'top-' + index" class="circle-button"></button>
		    </view>
		    <view class="middle">
		      <view class="button-row left">
		        <button v-for="index in gridLine" :key="'left-' + index" class="circle-button"></button>
		      </view>
		      <view class="inner-space">
				  <canvas canvas-id="canvas" :height="windowSize" width="windowSize"></canvas>
			  </view>
		      <view class="button-row right">
		        <button v-for="index in gridLine" :key="'right-' + index" class="circle-button"></button>
		      </view>
		    </view>
		    <view class="button-row bottom">
		      <button v-for="index in gridLine" :key="'bottom-' + index" class="circle-button"></button>
		    </view>
		  </view>
		</template>

		<!-- <canvas canvas-id="canvas" @touchstart="startBall"></canvas>
		<canvas canvas-id="canvas"></canvas> -->
		<button style="margin-top: 50px;" @click="startBall">开始</button>
	</view>
</template>

<script>
	export default {
		data () {
			return {
				ball: {
					x: 0,
					y: 0,
					vx: 0,
					vy: 2,
					radius: 5
				},
				diagonalsVisible:true,
				diagonalTimeout:null,
				isAnimating:false,
				requestId: null,
				diagonals: [], // 存储对角线位置的数组
				lastCollision: 0, // 上次碰撞的时间戳
				collisionThreshold: 100, // 碰撞阈值（毫秒）
				ballPath: [], // 存储小球移动的路径点
				gridLine: 8,
				windowSize: uni.getSystemInfoSync().windowWidth-84,
				lastDirection: null, // 存储最后一条对角线的方向
				lastPos: { row: 0, col: 0 }, // 存储最后一条对角线的位置
				lastDiagonal: { row: -1, col: -1, startToEnd: true } // 存储最后一条对角线的信息

			};
		},
		mounted () {
			const size = this.windowSize / this.gridLine;
			this.ball.x = size / 2;
			this.ball.y = size / 2;
			this.ball.vx = 1; // 初始速度
			this.ball.vy = 1;
			this.startBall()
		},
		methods: {
			drawBall (ctx) {
				ctx.beginPath();
				ctx.arc(this.ball.x, this.ball.y, this.ball.radius, 0, Math.PI * 2);
				ctx.fillStyle = "#00FF00";
				ctx.fill();
				ctx.closePath();
			},
			drawGrid (ctx) {
				const size = this.windowSize / this.gridLine;

				ctx.beginPath();
				for (let i = 0; i <= this.gridLine; i++) {
					ctx.moveTo(i * size, 0);
					ctx.lineTo(i * size, this.windowSize);
					ctx.moveTo(0, i * size);
					ctx.lineTo(this.windowSize, i * size);
				}
				ctx.strokeStyle = "#000";
				ctx.stroke();
			},
			drawDiagonals (ctx) {
				const size = this.windowSize / this.gridLine;
				if (!this.diagonalsVisible) return;
				this.diagonals.forEach(diagonal => {
					let x1 = diagonal.col * size;
					let y1 = diagonal.row * size;

					let x2, y2;

					// 根据对角线的方向决定终点坐标
					if (diagonal.startToEnd) {
						// 从左上到右下
						x2 = (diagonal.col + 1) * size;
						y2 = (diagonal.row + 1) * size;
					} else {
						// 从右上到左下
						y1 = (diagonal.row + 1) * size

						x2 = (diagonal.col + 1) * size;
						y2 = (diagonal.row) * size;
					}
					// const x2 = (diagonal.col + 1) * size;
					// const y2 = (diagonal.row + 1) * size;

					// 绘制对角线
					ctx.beginPath();
					ctx.lineWidth = 3;
					ctx.moveTo(x1, y1);
					ctx.lineTo(x2, y2);
					ctx.strokeStyle = "#3c9cff";
					ctx.stroke();

					// 计算并绘制对角线中心点
					const centerX = (x1 + x2) / 2;
					const centerY = (y1 + y2) / 2;
					ctx.beginPath();
					ctx.arc(centerX, centerY, 5, 0, 2 * Math.PI); // 以5为半径画圆
					ctx.fillStyle = "#FF0000"; // 设置中心点的颜色
					ctx.fill();
				});
				// 设置隐藏对角线的定时器
				  // if (this.diagonalTimeout) clearTimeout(this.diagonalTimeout); // 清除现有的定时器
				  this.diagonalTimeout = setTimeout(() => {
					  console.log("执行清除");
				    this.diagonalsVisible = false;
				    ctx.clearRect(0, 0, this.windowSize, this.windowSize); // 清除画布
				    // 这里假设 drawAll 会重新绘制所有除对角线外的内容
				    // this.drawAll(ctx); 
				  }, 3000); // 5秒后隐藏对角线
			},

			/**
			 * 每个格子只能有一条对角线.
			   第一条对角线总是从左上到右下的方向，随机出现在第一列的非第一行格子里。
			   从第二条对角线开始，根据上一条对角线反弹后的方向（上下左右）来决定新对角线的位置,新对角线出现在上一条对角线反弹后所在的行或列中
			   每条对角线的方向（startToEnd）是随机的
			**/
			generateDiagonals (numberOfDiagonals) {
				this.diagonals = [];
				const cols = this.gridLine; // 网格列数
				const rows = this.gridLine; // 网格行数
				let usedCells = new Set(); // 用于记录已使用的格子
				let lastRow = 0,
					lastCol = 0;
				let lastDirection = 'up'; // 初始球来的方向

				for (let i = 0; i < this.gridLine; i++) {
					let row, col, startToEnd;
					let attempts = 0; // 尝试次数计数器

					do {
						if (i === 0) {
							// 第一条对角线，避开第一行第一列
							row = Math.floor(Math.random() * (rows - 1)) + 1;
							col = 0;
							startToEnd = true;
						} else {
							// 生成随机步骤
							const random = Math.floor(Math.random() * this.gridLine)
							// 后续对角线
							if (lastDirection === 'right') {
								console.log("球从右来", lastRow, lastCol);
								row = lastRow;
								col = lastCol + random < cols ? lastCol + random : lastCol;
							} else if (lastDirection === 'left') {
								console.log("球从左来", lastRow, lastCol);
								row = lastRow;
								col = lastCol - random >= 0 ? lastCol - random : lastCol;
							} else if (lastDirection === 'down') {
								console.log("球从下来", lastRow, lastCol);
								row = lastRow - random < rows ? lastRow - random : lastRow;
								col = lastCol;
							} else { // lastDirection === 'up'
								console.log("球从上来", lastRow, lastCol);
								row = lastRow + random >= 0 ? lastRow + random : lastRow;
								col = lastCol;
							}
							// 确保新对角线在画布内
							  row = Math.max(0, Math.min(row, cols - 1));
							  col = Math.max(0, Math.min(col, cols - 1));
							startToEnd = Math.random() < 0.5; // 随机设置对角线方向
						}

						if (++attempts > 100) { // 设置尝试次数上限
							console.error("无法找到合适的对角线位置");
							return; // 退出函数
						}
					} while (usedCells.has(`${row}-${col}`));

					this.diagonals.push({ row, col, startToEnd });
					usedCells.add(`${row}-${col}`);
					lastRow = row;
					lastCol = col;
					lastDirection = this.updateDirection(lastDirection, startToEnd); // 更新反弹方向
				}
			},


			highlightExitEdge (edge) {
				console.log("出口位置",edge);
				this.stopBall()
				const ctx = uni.createCanvasContext('canvas', this);
				const canvasWidth = this.windowSize;
				const canvasHeight = this.windowSize;

				ctx.beginPath();
				ctx.lineWidth = 5;
				ctx.strokeStyle = 'red';

				switch (edge) {
					case 'left':
						ctx.moveTo(0, 0);
						ctx.lineTo(0, canvasHeight);
						break;
					case 'right':
						ctx.moveTo(canvasWidth, 0);
						ctx.lineTo(canvasWidth, canvasHeight);
						break;
					case 'top':
						ctx.moveTo(0, 0);
						ctx.lineTo(canvasWidth, 0);
						break;
					case 'bottom':
						ctx.moveTo(0, canvasHeight);
						ctx.lineTo(canvasWidth, canvasHeight);
						break;
				}
				ctx.stroke();
				ctx.draw()
			},
			checkBallExit () {
				const canvasWidth = this.windowSize;
				const canvasHeight = this.windowSize;

				// 判断小球是否离开画布
				if (this.ball.x < 0 || this.ball.x > canvasWidth || this.ball.y < 0 || this.ball.y > canvasHeight) {
					// 确定最后接触的边缘
					let edge;
					if (this.ball.x < 0) edge = 'left';
					else if (this.ball.x > canvasWidth) edge = 'right';
					else if (this.ball.y < 0) edge = 'top';
					else edge = 'bottom';

					// 高亮显示出口边缘
					// this.highlightExitEdge(edge);
					// 小球离开画布
					console.log("离开画布",this.ball);
					return true;
					
				} else {
					return false; // 小球仍在画布内
					console.log("没离开画布");
				}
			},
			drawBallPath (ctx) {
				const radius = 3; // 圆点的半径
				const glowRadius = 20; // 发光效果的范围

				for (let i = 0; i < this.ballPath.length; i++) {
					ctx.beginPath();
					ctx.arc(this.ballPath[i].x, this.ballPath[i].y, radius, 0, 2 * Math.PI);
					// 设置发光效果
					ctx.fillStyle = '#FFFFFF';
					ctx.shadowBlur = glowRadius;
					ctx.shadowColor = 'rgba(255, 255, 255, 0.5)';
					ctx.fill();
				}

				// 重置阴影效果，以免影响后续的绘制
				ctx.shadowBlur = 0;
			},



			updateBall () {
				const canvasWidth = this.windowSize;
				const canvasHeight = this.windowSize;
				const cellSize = canvasWidth / this.gridLine;

				// 更新球的位置
				this.ball.x += this.ball.vx;
				this.ball.y += this.ball.vy;

				// 检查小球是否离开画布
				if (this.checkBallExit()) {
					console.log("looooo");
					this.ball.vy = 0;
					this.ball.vx = 0;
					// 如果小球离开了画布，停止动画循环
					this.stopBall()
					return; // 退出函数，防止进一步更新
				}

				// 将当前位置添加到路径数组
				if (this.ballPath.length === 0 || this.shouldAddToPath(this.ballPath[this.ballPath.length - 1], this.ball.x, this.ball.y)) {
					this.ballPath.push({ x: this.ball.x, y: this.ball.y });
				}
				// 可以选择限制路径长度
				// if (this.ballPath.length > 300) {
				// 	this.ballPath.shift(); // 移除最旧的点
				// }

				// 检测墙壁碰撞
				// if (this.ball.x + this.ball.vx > canvasWidth - this.ball.radius || this.ball.x + this.ball.vx < this.ball.radius) {
				// 	this.ball.vx = -this.ball.vx;
				// }
				// if (this.ball.y + this.ball.vy > canvasHeight - this.ball.radius || this.ball.y + this.ball.vy < this.ball.radius) {
				// 	this.ball.vy = -this.ball.vy;
				// }

				// 检测对角线碰撞
				const currentTime = Date.now();
				this.diagonals.forEach(diagonal => {
					const midpoint = this.calculateDiagonalMidpoint(diagonal);
					const distanceToMidpoint = this.distance(this.ball.x, this.ball.y, midpoint.x, midpoint.y);

					if (distanceToMidpoint <= this.ball.radius && currentTime - this.lastCollision > this.collisionThreshold) {
						// 更新上次碰撞时间
						this.lastCollision = currentTime;
						if (diagonal.startToEnd) {
							// 对于从左上到右下的对角线
							let tempVx = this.ball.vx;
							this.ball.vx = this.ball.vy;
							this.ball.vy = tempVx;
						} else {
							// 对于从右上到左下的对角线
							let tempVx = this.ball.vx;
							this.ball.vx = -this.ball.vy
							this.ball.vy = -tempVx; // 向左反弹
						}
					}
				});
				// 判断小球是否离开画布
				// this.checkBallExit();
			},
			calculateDiagonalMidpoint (diagonal, cellSize) {
				const x1 = diagonal.col * cellSize;
				const y1 = diagonal.row * cellSize;
				const x2 = (diagonal.col + 1) * cellSize;
				const y2 = (diagonal.row + 1) * cellSize;

				// 对角线中点坐标
				return {
					x: (x1 + x2) / 2,
					y: (y1 + y2) / 2
				};
			},
			startBall () {
				this.resetGame()
				clearTimeout(this.diagonalTimeout)
				const ctx = uni.createCanvasContext('canvas', this);

				// 首先停止任何已存在的动画循环
				if (this.requestId) {
					cancelAnimationFrame(this.requestId);
				}

				this.generateDiagonals(); // 生成对角线位置

				const loop = () => {
					 if (this.isAnimating) {
					    // 清除并填充画布
					    ctx.fillStyle = '#1c1e1f'; // 设置背景色
					    ctx.fillRect(0, 0, this.windowSize, this.windowSize);
					    // ctx.clearRect(0, 0, this.windowSize, uni.getSystemInfoSync().windowHeight);
					    this.drawBallPath(ctx); // 绘制小球轨迹
					    this.drawBall(ctx);
					    this.drawGrid(ctx);
					    this.drawDiagonals(ctx);
					    this.drawBall(ctx);
					    this.updateBall();
					    ctx.draw();
					    this.requestId = requestAnimationFrame(loop);
					}
				};
				this.isAnimating = true;
				

				loop();
				// this.requestId = requestAnimationFrame(loop);
			},
			stopBall () {
				if (this.requestId) {
					this.isAnimating = false;
					cancelAnimationFrame(this.requestId);
					this.requestId = null
				}
			},
			resetGame () {
				// 停止当前动画循环
				if (this.requestId) {
					cancelAnimationFrame(this.requestId);
					this.requestId = null;
				}

				// 重置小球状态
				const size = this.windowSize / this.gridLine;
				this.ball.x = size / 2;
				this.ball.y = size / 2;
				this.ball.vx = 0;
				this.ball.vy = 2;

				// 可以在这里重置其他状态，比如清空对角线数组等
				this.diagonals = [];
				this.ballPath = []
			},
			// 根据对角线方向和当前运动方向更新反弹方向
			updateDirection (currentDirection, startToEnd) {
				// 假设反弹方向与对角线方向相关
				// 例如，如果当前方向是向下且对角线是从左上到右下，反弹后方向可能变为向右
				// 此处要注意区分绝对方向和相对方向 currentDirection表示小球的运动方向（来）

				switch (currentDirection) {
					case 'down':
						return startToEnd ? 'left' : 'right';
					case 'up':
						return startToEnd ? 'right' : 'left';
					case 'left':
						return startToEnd ? 'down' : 'up';
					case 'right':
						return startToEnd ? 'up' : 'down';
					default:
						return 'down'; // 默认方向
				}
			},
			// 从数组中寻找最接近目标数字的数
			findClosest (arr = [], num) {
				let curr = arr[0];
				let diff = Math.abs(num - curr);
				for (let val = 0; val < arr.length; val++) {
					let newdiff = Math.abs(num - arr[val]);
					if (newdiff < diff) {
						diff = newdiff;
						curr = arr[val];
					};
				};
				return curr;
			},
			// 辅助方法：根据一定的间隔判断是否应该添加新的路径点
			shouldAddToPath (lastPoint, x, y) {
				const minDistance = 10; // 最小间隔距离
				return this.distance(lastPoint.x, lastPoint.y, x, y) > minDistance;
			},
			// 辅助函数：计算两点之间的距离
			distance (x1, y1, x2, y2) {

				return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
			},

			// 辅助函数：计算点到线段的最短距离
			pointToLineDistance (x, y, x1, y1, x2, y2) {
				const A = x - x1;
				const B = y - y1;
				const C = x2 - x1;
				const D = y2 - y1;

				const dot = A * C + B * D;
				const len_sq = C * C + D * D;
				const param = len_sq !== 0 ? dot / len_sq : -1;

				let xx, yy;

				if (param < 0) {
					xx = x1;
					yy = y1;
				} else if (param > 1) {
					xx = x2;
					yy = y2;
				} else {
					xx = x1 + param * C;
					yy = y1 + param * D;
				}

				return this.distance(x, y, xx, yy);
			},

			// 碰撞检测逻辑
			checkCollision (ball, diagonal, cellSize) {
				let x1, y1, x2, y2;

				// 根据对角线方向设置端点
				if (diagonal.startToEnd) {
					// 从左上到右下
					x1 = diagonal.col * cellSize;
					y1 = diagonal.row * cellSize;
					x2 = (diagonal.col + 1) * cellSize;
					y2 = (diagonal.row + 1) * cellSize;
				} else {
					// 从右上到左下
					x1 = (diagonal.col + 1) * cellSize;
					y1 = diagonal.row * cellSize;
					x2 = diagonal.col * cellSize;
					y2 = (diagonal.row + 1) * cellSize;
				}

				// 计算圆心到线段的最短距离
				const dist = this.pointToLineDistance(ball.x, ball.y, x1, y1, x2, y2);
				// 如果距离小于等于球的半径，发生碰撞
				return dist <= ball.radius;
			},
			calculateDiagonalMidpoint (diagonal) {
				const cellSize = this.windowSize / this.gridLine;
				const x1 = diagonal.col * cellSize;
				const y1 = diagonal.row * cellSize;
				const x2 = (diagonal.col + 1) * cellSize;
				const y2 = (diagonal.row + 1) * cellSize;

				// 对角线中心点坐标
				return {
					x: (x1 + x2) / 2,
					y: (y1 + y2) / 2
				};
			}
		},
		onUnload () {
			this.stopBall();
		}
	};
</script>


<style>
	canvas {
		width: 100%;
		height: 100%;
	}
	.container {
	  display: flex;
	  flex-direction: column;
	  justify-content: center;
	  align-items: center;
	  width:100vw;
	  /* height: 100vh; */
	}
	
	.button-row {
	  display: flex;
	  justify-content: center;
	  align-items: center;
	}
	
	.top, .bottom {
	  width: 80vw;
	  display: flex;
	  justify-content: space-around;
	}
	
	.middle {
	  display: flex;
	  width: 100%;
	  height: 100%;
	  justify-content: space-around;
	}
	
	.left, .right {
		height: 80vw;
		display: flex;
		justify-content: space-around;
	  flex-direction: column;
	}
	
	.inner-space {
	  width: 100%;  /* Adjust as needed */
	  height: 80vw;
	  background-color: white; /* White space in the middle */
	}
	
	.circle-button {
	  width: 30px;
	  height: 30px;
	  /* border-radius: 50%; */
	  margin: 5px;
	  border: 2px solid #666; /* Adjust border color as needed */
	  background-color: #fff; /* Adjust button color as needed */
	}

</style>